// Copyright (C) 2023 即时通讯网(52im.net) & Jack Jiang.
// The RainbowChat Project. All rights reserved.
// 
// 【本产品为著作权产品，合法授权后请放心使用，禁止外传！】
// 【本次授权给：<北京小羊驼科技有限公司>，授权编号：<NT231212144350>，代码指纹：<A.702363430.550>，技术对接人微信：<ID: wxid_wbyootvkdcgj22>】
// 【授权寄送：<收件：苏先生、地址：北京市大兴区北京密码西区6号楼1单元301、电话：18613885610、邮箱：bd@huiyuanxiang-inc.com>】
// 
// 【本系列产品在国家版权局的著作权登记信息如下】：
// 1）国家版权局登记名(简称)和权证号：RainbowChat    （证书号：软著登字第1220494号、登记号：2016SR041877）
// 2）国家版权局登记名(简称)和权证号：RainbowChat-Web（证书号：软著登字第3743440号、登记号：2019SR0322683）
// 3）国家版权局登记名(简称)和权证号：RainbowAV      （证书号：软著登字第2262004号、登记号：2017SR676720）
// 4）国家版权局登记名(简称)和权证号：MobileIMSDK-Web（证书号：软著登字第2262073号、登记号：2017SR676789）
// 5）国家版权局登记名(简称)和权证号：MobileIMSDK    （证书号：软著登字第1220581号、登记号：2016SR041964）
// * 著作权所有人：江顺/苏州网际时代信息科技有限公司
// 
// 【违法或违规使用投诉和举报方式】：
// 联系邮件：jack.jiang@52im.net
// 联系微信：hellojackjiang
// 联系QQ号：413980957
// 授权说明：http://www.52im.net/thread-1115-1-1.html
// 官方社区：http://www.52im.net
package com.x52im.rbchat.logic.chat_friend.gift;

import android.app.Activity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import com.eva.android.widget.SimpleGridView;
import com.eva.android.widget.SimpleGridView.DefaultElementDTO;
import com.eva.android.widget.SimpleGridView.DefaultItemAction;
import com.eva.android.widget.SimpleGridView.DefaultListAdapter;
import com.eva.android.widget.SimpleViewPager;
import com.eva.epc.common.util.CommonUtils;
import com.eva.epc.common.util.MapNoHash;
import com.x52im.rbchat.Const;
import com.x52im.rbchat.MyApplication;
import com.x52im.rbchat.R;
import com.x52im.rainbowchat.http.logic.dto.RosterElementEntity;
import com.x52im.rbchat.logic.chat_friend.gift.model.GiftInPackage;
import com.x52im.rbchat.logic.chat_friend.gift.model.GiftInPackageMeta;
import com.x52im.rbchat.logic.chat_friend.gift.model.GiftsMeta;
import com.x52im.rbchat.utils.IntentFactory;

import java.util.ArrayList;
import java.util.Observable;
import java.util.Observer;

/**
 * 礼品工具界面：我的礼品包.
 * 
 * @author Jack Jiang(http://www.52im.net/space-uid-1.html)
 * @since 2.5
 */
public class GiftsPagerForPackage extends SimpleViewPager
{
	protected Activity parentActivity = null;
	
	/** 
	 * 收到好友发过来的礼品观察者对象.
	 * 目前此观察者只要用于聊天界面中在收到礼品后能即时刷新“我的礼品包”的ui展现之用. */
	private Observer receivedGiftObserverForGiftToolsUI = new Observer(){
		@Override
		public void update(Observable observable, Object data)
		{
			Object[] datas = (Object[])data;
			final String giftIdent = (String)datas[0];
			GiftInPackageMeta gim = (GiftInPackageMeta)datas[1];
//			notifyAdapterDataSetChanged();
			
			//** 把数据刷新到UI上
			// 为什么把数据刷新到ui上不简单地notifyDataSetChanged列表，而要重整整个背包的ui呢？
			// 原因是简单地notifyDataSetChanged是不是刷新ui的，因为本类中的Adapter中的数据模型不
			// 是像聊天消息一样是数据模型的同一个引用，本类中是一个拷贝。另一个原因是，因为重整ui
			// 涉及到自动分页（自动计算分页数等并重新结构adapter和ui）等，而普通的notifyDataSetChanged
			// 是不可能完成的。好在用户不太可能频繁收到礼品，次数应该并不太多，所以性能应该还是在
			// 忍受的范围内，等实际应用中性能实在不行了再想办法吧！！
			GiftsPagerForPackage.this.refreshUI(parentActivity, gim);
		}
	};
	
	public GiftsPagerForPackage(final Activity context)
	{
		super(context
				, R.layout.chatting_gift_package_viewpager
				, R.id.chatting_gift_package_viewpager_layoutBottom
				, R.id.chatting_gift_package_viewpager_viewPager);
		
		// 
		this.parentActivity = context;
	}
	
	public Observer getReceivedGiftObserverForGiftToolsUI()
	{
		return receivedGiftObserverForGiftToolsUI;
	}

//	/**
//	 * 通知列表ui更新.
//	 */
//	public void notifyAdapterDataSetChanged()
//	{
//		viewPager.getAdapter().notifyDataSetChanged();
//	}
	
	/**
	 * 用新场景数据刷新界面显示的核心实现方法.
	 * 
	 * @param context
	 * @param scenceMeta
	 * @see #putDatas(ArrayList, ArrayList)
	 */
	public void refreshUI(Activity context, GiftInPackageMeta scenceMeta)
	{
		// 每页显示的礼品数
		int num_per_page = Const.GIFTS_TOOLS_PAGER_EVERY_PAGE_NUM;

		// 要显示的所有礼品集合
		ArrayList<DefaultElementDTO> listDatas = getListDatas(context, scenceMeta);

		// 提交新数据并刷新ui显示
		this.putDatas(getViews(context, listDatas, num_per_page), getPagerIndicators(context, listDatas.size(), num_per_page));
		
		// 通知外部刷新礼品数的ui（此处场景是完全切换数据时，gridView里面的刷新使用notifyDatasetChanged方法即可）
		onGiftsQuatityGiftsQuatityChanged(getAllGiftsQuantity());
	}
	
	// 返回的界面上的页面ui集合
	protected ArrayList<View> getViews(Activity context, ArrayList<DefaultElementDTO> listDatas
			, int num_per_page)
	{
		ArrayList<View> views = new ArrayList<View>();

		// 遍历所有元素（并自动按定义的每页显示数进行分页）
		ArrayList<DefaultElementDTO> childListDatas = null;
		for(int i = 0; i < listDatas.size();i++)
		{
			// 当整页时，进行分页处理
			if(i % num_per_page == 0)
			{
				// 当childListDatas == null时是i==0时的特殊情况，注意一下！
				if(childListDatas != null)
					views.add(createGridViewObj(context, childListDatas));

				childListDatas = new ArrayList<DefaultElementDTO>();
			}
			childListDatas.add(listDatas.get(i));

			// 特殊情况处理：上述算法中最后一页是无法加入到views中的，所以要特殊处理哦
			if(i == (listDatas.size() - 1))
				views.add(createGridViewObj(context, childListDatas));
		}
		return views;
	}
	
	// 返回界面上的指示器ui组件
	protected ArrayList<PaggerIndicator> getPagerIndicators(final Activity context, int allFaceCount, int num_per_page)
	{
		ArrayList<PaggerIndicator> ids = new ArrayList<PaggerIndicator>();
		
		// 指示器个数 = 无条件进位【总表情集数 / 每页数】的结果（即2.1=3页，2=2页，2.9=3页）
		int indicatorCount = CommonUtils.getLikePageNum(allFaceCount, num_per_page);
		
		// 按个数建立指示器ui组件
		for(int i = 0; i < indicatorCount; i++)
			ids.add(new DefaultPaggerIndicatorImageView(context){
				public void setIndicatorSelected(boolean selected)
				{
					if(selected)
						this.setImageResource(R.drawable.chatting_morefunc_pager_indicator_selected_icon);
					else
						this.setImageResource(R.drawable.chatting_morefunc_pager_indicator_unselected_icon);
				}
			});

		return ids;
	}
	
	// 返回所有元素的数据集
	protected ArrayList<DefaultElementDTO> getListDatas(final Activity context, GiftInPackageMeta scenceMeta)
	{
		// 要返回的所有元素列表
		ArrayList<DefaultElementDTO> listDatas = new ArrayList<DefaultElementDTO>();
		
		// 遍历表情集元始数据模型
		MapNoHash<String, GiftInPackage> facesMap = scenceMeta.getGiftsInPackageData();
		for(String key : facesMap.keys())
		{
			GiftInPackage g = facesMap.get(key);
			listDatas.add(new DefaultElementDTO(createAction(context, g), g.getGift_name() , null));
		}
		
		return listDatas;
	}
	
	// 根据传进来的每页元素数据集，生成该页的GridView对象
	protected SimpleGridView createGridViewObj(Activity context, ArrayList<DefaultElementDTO> childListDatas)
	{
		return new SimpleGridView(context 
				, R.layout.chatting_gift_package_gridview, R.id.chatting_gift_package_gridview_id
				, R.layout.chatting_gift_package_gridview_item, R.id.chatting_gift_package_gridview_item_nameView, R.id.chatting_gift_package_gridview_item_imageView
				, childListDatas)
		{
			// 重写adapter创建方法，实现自定义的view展现逻辑
			protected DefaultListAdapter createListAdapter(
					Activity context
					, final int maingridviewitem_layout_res_id
					, final int maingridviewitem_text_view_id
					, final int maingridviewitem_image_view_id
					, ArrayList<DefaultElementDTO> listDatas)
			{
				DefaultListAdapter adapter = new ListAdapterImpl(context
						, maingridviewitem_layout_res_id
						, maingridviewitem_text_view_id 
						, maingridviewitem_image_view_id){
					@Override
					public void notifyDataSetChanged()
					{
						super.notifyDataSetChanged();
						
						// 通知外部刷新礼品数的ui
						onGiftsQuatityGiftsQuatityChanged(getAllGiftsQuantity());
					}
				}; 
				// 
				adapter.setListData(listDatas);
				return adapter;
			}
		};
	}
	
	protected DefaultItemAction createAction(final Activity context, Object indentId)
	{
		return new DefaultItemAction(indentId){
			@Override
			public void actionPerformed(Object obj)
			{
//				WidgetUtils.showToast(context, "选中的obj="+obj);
				if(obj != null && obj instanceof GiftInPackage)
				{
					// 表情的id（一个表情是一个文件夹，表情的id就是文件夹名）
					final GiftInPackage faceIdentId = (GiftInPackage)obj;
					//
					fireAction(faceIdentId);
				}
			}
		};
	}
	protected void fireAction(final GiftInPackage gift)
	{
		if(gift != null)
		{
			RosterElementEntity localRee = MyApplication.getInstance(parentActivity)
					.getIMClientManager().getLocalUserInfo();
			if(localRee != null)
			{
				String localUid = localRee.getUser_uid();
				String gifIdent = gift.getGift_ident();
				parentActivity.startActivity(IntentFactory.createGiftHistoryIntent(parentActivity, localUid, gifIdent));
			}
		}
	}
	
	/**
	 * 返回当前背包里的礼品总数（同一礼品的多个不会按1个计）。
	 * <p>
	 * 此方法返回的是所有页面（即整个背包的数量）。
	 * 
	 * @return
	 */
	public int getAllGiftsQuantity()
	{
		int allQuantity = 0;
		
		ArrayList<View> allGridViews = this.getViews();
		for(View gridView : allGridViews)
		{
			ListAdapterImpl lai = (ListAdapterImpl)(((SimpleGridView)gridView).getGridViewAdapter());
			allQuantity += lai.getGiftsQuantityInThisGrid();
		}
		
		return allQuantity;
	}
	
	/**
	 * 当礼品数量改变时的UI通知实现方法。
	 * 
	 * @param allGiftsQuantity
	 * @see #nofityForPackageGiftsNumChanged(int)
	 */
	public void onGiftsQuatityGiftsQuatityChanged(int allGiftsQuantity)
	{
//		// 礼品总数
//		int quantity = getGiftsQuantity();
		// 通知外部刷新礼品数的ui
		nofityForPackageGiftsNumChanged(allGiftsQuantity);
		
		// 当礼品总数为0或不为o时切换礼品包的ui显示
		View viewPaggerUI = mLayoutInflater.findViewById(R.id.chatting_gift_package_viewpager_rl);
		View nullUI = mLayoutInflater.findViewById(R.id.chatting_gift_package_null_ll);
		if(allGiftsQuantity > 0)
		{
			viewPaggerUI.setVisibility(View.VISIBLE);
			nullUI.setVisibility(View.GONE);
		}
		else
		{
			viewPaggerUI.setVisibility(View.GONE);
			nullUI.setVisibility(View.VISIBLE);
		}
	}
	/**
	 * 当前列表数据刷新时，本方法将携带当前礼品总数来通知ui实现类来刷新相应的ui显示。
	 */
	protected void nofityForPackageGiftsNumChanged(int quantity)
	{
		// default do nothing
	}
	
	//-----------------------------------------------------------------------------------------
	private class ListAdapterImpl extends DefaultListAdapter
	{
		public ListAdapterImpl(Activity context,
				int maingridviewitem_layout_res_id,
				int maingridviewitem_text_view_id,
				int maingridviewitem_image_view_id)
		{
			super(context, maingridviewitem_layout_res_id, maingridviewitem_text_view_id,
					maingridviewitem_image_view_id);
		}
		
		@Override
		public View getView(final int position, View convertView, ViewGroup parent)
		{
			//列表item上的：
			TextView viewText = null;
			//列表item上的：
			ImageView viewImage = null;
			TextView viewPrice = null;
			TextView viewCount = null;
			
			//---------------------------------------------------------------------------------------- （1）UI初始化
			//当的item布局实例已经存在（不在存，意味着这个item刚好从不可见区移到可见区时）
			//** 根据android的列表ui实现，为了节比资源占用，假如列表有100行而可见区显示5行，那么任何时候
			//** 这个列表中只会有5个item的UI存在，其它的item都是当被转到可见区时自动把自
			//** 已的数据实时地更新列UI上，以便查看，也就是说item的UI并不是与后台数据一
			//** 一对应的，所以正如API文档里说的，convertView并不能确保它总能按你的想法保持不为null
			boolean needCreateItem = (convertView == null);
			//正在操作的列表行的数据集
			final DefaultElementDTO rowData = listData.get(position);
			final GiftInPackage extraData = (GiftInPackage)rowData.get__ident__();
			
			if (needCreateItem)
				//明细item的UI实例化
				convertView = layoutInflater.inflate(itemResId, null);
			//item里的操作组件实例
			viewText = (TextView) convertView.findViewById(maingridviewitem_text_view_id);////R.id.chatting_list_view_bottom_waves_list_item_txt);
			viewImage = (ImageView) convertView.findViewById(maingridviewitem_image_view_id);//R.id.chatting_list_view_bottom_waves_list_item_image);
			viewPrice = (TextView) convertView.findViewById(R.id.chatting_gift_package_gridview_item_priceView);
			viewCount = (TextView) convertView.findViewById(R.id.chatting_gift_package_gridview_item_countView);
			
			//---------------------------------------------------------------------------------------- （2）增加事件处理器
			//各操作组件的事件监听器只需要在convertView被实例化时才需要重建（convertView需要被实例化
			//当然就意味着它上面的所有操作组件都已经重新新建了）
			//** 关于事件处理器的说明：事件处理器的增加其实可以不这么麻烦，直接每getView一次就给组件new一个处理器，
			//** 这样做的好处是简单，但显然存在资源浪费（每刷新一次view就新建监听器）。而现在的实现就跟Android的列表
			//** 实现原理一样，在切换到下一组item前，监听器永远只有一屏item的数量（刷新时只需要即时刷新对应item的数据到
			//** 它的监听器里），这样就节省了资源开销！
			if(needCreateItem)
			{
				//
			}

			//---------------------------------------------------------------------------------------- （3）
			// ********** 设置文本数据
			viewText.setText(extraData.getGift_name());
			GiftsMeta.showGiftDrawable(context, viewImage, extraData.getRes_drawable_id());
			viewPrice.setText(String.valueOf(extraData.getPrice()));
			viewCount.setText(String.valueOf(extraData.getQuantity()));
			
			return convertView;
		}
		
		/**
		 * 返回当前背包里的本页礼品总数（同一礼品的多个不会按1个计）。
		 * <p>
		 * 注意：目前的背包礼品分页机制里，每一而都是一个独立的GridView，所以
		 * 此方法只能统到的是该页的总礼品数而非所有页哦（即整个背包哦）.
		 * 
		 * @return
		 */
		public int getGiftsQuantityInThisGrid()
		{
			int quantity = 0;
			if(listData != null)
			{
				for(DefaultElementDTO rowData : listData)
				{
					if(rowData != null)
					{
						final GiftInPackage extraData = (GiftInPackage)rowData.get__ident__();
						quantity += extraData.getQuantity();
					}
				}
			}
			
			return quantity;
		}
	}
}

